package com.cpit.qualitycontrol.service.impl;

import com.cpit.platform.common.constant.SystemConstant;
import com.cpit.platform.common.entity.TableDataQueryCondition;
import com.cpit.platform.common.entity.TableJsonData;
import com.cpit.platform.dao.OrganizationRepository;
import com.cpit.platform.dao.UserRepository;
import com.cpit.platform.dao.UserToRoleRepository;
import com.cpit.platform.dto.Organization;
import com.cpit.platform.dto.User;
import com.cpit.platform.dto.UserToRole;
import com.cpit.qualitycontrol.common.constant.RoleConstant;
import com.cpit.qualitycontrol.common.enums.SubTaskProcessStatusEnum;
import com.cpit.qualitycontrol.common.enums.SubTaskStatusEnum;
import com.cpit.qualitycontrol.common.enums.TaskProcessNameEnum;
import com.cpit.qualitycontrol.common.enums.WorkOrderStatusEnum;
import com.cpit.qualitycontrol.dao.*;
import com.cpit.qualitycontrol.dao.jpqlquery.WorkOrderQueryRepository;
import com.cpit.qualitycontrol.entity.*;
import com.cpit.qualitycontrol.service.ProcessRuleService;
import com.cpit.qualitycontrol.service.SubTaskService;
import com.cpit.qualitycontrol.service.UserToProductLineService;
import com.cpit.qualitycontrol.service.WorkOrderService;
import com.cpit.qualitycontrol.vo.ImportWorkOrderVo;
import com.cpit.qualitycontrol.vo.SubTaskCreateVo;
import com.cpit.qualitycontrol.vo.WorkOrderCreateVo;
import com.github.pagehelper.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by xxx on 2017/10/1.
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class WorkOrderServiceImpl implements WorkOrderService {

    private final String loggerName = this.getClass().getName();

    @Autowired
    WorkOrderCrudRepository workOrderCrudRepository;

    @Autowired
    WorkOrderQueryRepository workOrderQueryRepository;

    @Autowired
    SubTaskCrudRepository subTaskCrudRepository;

    @Autowired
    OrganizationRepository organizationRepository;

    @Autowired
    ActivitiServiceImpl activitiService;

    @Autowired
    SubTaskBusinessDataCrudRepository subTaskBusinessDataCrudRepository;

    @Autowired
    SubTaskProcessInfoCrudRepository subTaskProcessInfoCrudRepository;

    @Autowired
    DeviceRepository deviceRepository;

    @Autowired
    WorkOrderTypeRepository workOrderTypeRepository;

    @Autowired
    UserRepository userRepository;

    @Autowired
    CommonServiceImpl commonService;

    @Autowired
    SubTaskService subTaskService;

    @Autowired
    ProcessRuleService processRuleService;

    @Autowired
    UserToRoleRepository userToRoleRepository;

    @Autowired
    private UserToProductLineService userToProductLineService;

    @Override
    public List<WorkOrder> createWorkOrder(Integer createUserId, WorkOrderCreateVo workOrderCreateVo) throws Exception {

        List<SubTaskCreateVo> subTaskCreateVoList = workOrderCreateVo.getSubTaskCreateVoList();
        if (subTaskCreateVoList == null || subTaskCreateVoList.size() == 0) {
            throw new Exception("工单中没有子任务，请添加！");
        }

        List<String> deviceIdList = workOrderCreateVo.getDeviceIdList();
        if (deviceIdList == null || deviceIdList.size() == 0) {
            throw new Exception("工单中没有设备，请添加！");
        }

        List<WorkOrder> workOrderList = new ArrayList<>();
        for (String deviceId : deviceIdList) {
            WorkOrder workOrder = createWorkOrderOneDevice(createUserId, workOrderCreateVo.getSubTaskCreateVoList(), deviceId);
            workOrderList.add(workOrder);
        }
        return workOrderList;
    }

    @Override
    public List<WorkOrder> createWorkOrderByExcel(Integer createUserId, List<ImportWorkOrderVo> importWorkOrderVoList) throws Exception {
        if ((importWorkOrderVoList == null || importWorkOrderVoList.size() == 0)) {
            throw new Exception("没有待创建工单，请添加！");
        }

        List<WorkOrder> workOrderList = new ArrayList<>();
        for (ImportWorkOrderVo importWorkOrderVo : importWorkOrderVoList) {
            WorkOrder workOrder = createWorkOrderOneDevice(createUserId, importWorkOrderVo.getSubTaskCreateVoList(), importWorkOrderVo.getDeviceId());
            workOrderList.add(workOrder);
        }
        return workOrderList;
    }

    @Override
    public WorkOrder createWorkOrderOneDevice(Integer createUserId,
                                              List<SubTaskCreateVo> subTaskCreateVoList, String deviceId) throws Exception {

        //根据工单类型检查是否可以创建子任务
        checkWorkOrderTypeDuplicateCreate(subTaskCreateVoList, deviceId);

        //创建工单
        WorkOrder workOrder = new WorkOrder();

        //获取项目名称
        String projectName = deviceRepository.findProjectNameById(deviceId);
        // builder workOrderName
        String workOrderName = projectName + "-" + deviceId;
        workOrder.setWorkOrderName(workOrderName);
        workOrder.setDeviceId(deviceId);

        //获取工单创建人信息
        User user = userRepository.findById(createUserId);
        workOrder.setCreateWorkOrderUserId(createUserId);
        workOrder.setCreateWorkOrderUserName(user.getDisplayName());
        workOrder = workOrderCrudRepository.save(workOrder);

        //启动工作流，流转到待分派任务，为普天人员分配待分派工单任务
        List<Integer> assignUsers = commonService.getPotevioEngineeringDeptUserIds();
        if (assignUsers == null || assignUsers.size() == 0) {
            throw new Exception("没有查找到工程部人员，请添加！");
        }

        //启动流程，分配待分派工单任务
        String processInstanceId = activitiService
                .createWorkOrder(createUserId, String.valueOf(workOrder.getWorkOrderId()));

        //循环创建子任务
        SubTask subTask = null;
        //施工企业组织机构IdLISt,NameList
        List<Long> organizationIdList = new ArrayList<>();
        List<String> organizationNameList = new ArrayList<>();
        for (SubTaskCreateVo subVo : subTaskCreateVoList) {
            subTask = new SubTask();

            organizationIdList.add(subVo.getOrganizationId());
            //根据组织机构ID查询组织机构
            Organization organization = organizationRepository.findById(subVo.getOrganizationId().intValue());
            organizationNameList.add(organization.getName());

            //工单类型名称
            String workOrderTypeName = workOrderTypeRepository.getOne(subVo.getWorkOrderType()).getName();

            subTask.setSubTaskName(projectName + "-" + deviceId + "-" + workOrderTypeName);
            subTask.setWorkOrderId(workOrder.getWorkOrderId());
            subTask.setDeviceId(deviceId);
            subTask.setCheckTask(subVo.getCheckTask());
            subTask.setWorkOrderTypeId(subVo.getWorkOrderType());
            subTask.setOrganizationTeamId(subVo.getOrganizationId());
            subTask.setOrganizationTeamName(organization.getName());
            subTask.setDescription(subVo.getDescription());
            subTask.setActProcInstId(processInstanceId);

            subTaskCrudRepository.save(subTask);
        }

        //设置施工企业IDs,Names
        String organizationIds = StringUtils.collectionToDelimitedString(organizationIdList, ",");
        String organizationNames = StringUtils.collectionToDelimitedString(organizationNameList, ",");
        workOrder.setConstructionTeamIds(organizationIds);
        workOrder.setConstructionTeamNames(organizationNames);

        //工单表保存实例ID
        workOrder.setActProcInstId(processInstanceId);
        return workOrderCrudRepository.save(workOrder);
    }


    private void checkWorkOrderTypeDuplicateCreate(List<SubTaskCreateVo> subTaskCreateVoList,
                                                   String deviceId) throws Exception {

        StringBuilder errorSB = new StringBuilder();
        for (SubTaskCreateVo subTaskCreateVo : subTaskCreateVoList) {
            WorkOrderType workOrderType = workOrderTypeRepository
                    .findOne(subTaskCreateVo.getWorkOrderType());

            if (workOrderType.getDuplicateTaskFlag() == false) {
                Long countSubTask = subTaskCrudRepository
                        .countByWorkOrderTypeIdAndDeviceId(subTaskCreateVo.getWorkOrderType(), deviceId);

                if (countSubTask > 0) {
                    errorSB.append("已存在【").append(workOrderType.getName()).append("】任务!");
                }
            }
        }
        if (errorSB.length() > 0) {
            throw new Exception("编号为：" + deviceId + " 的设备，" + errorSB.toString());
        }

    }

    private Boolean isEnginneringDept(Integer userId) {
        List<UserToRole> userToRoleList = userToRoleRepository.findByUserId(userId);

        //判断是否是工程部人员
        List<Integer> roleIdList = userToRoleList.stream().map(
                userToRole -> userToRole.getRoleId()).collect(Collectors.toList());

        return roleIdList.contains(RoleConstant.ROLE_POTEVIO_ENGINEERING_DEPT);
    }

    private Boolean isConstructionTeam(Integer userId) {
        List<UserToRole> userToRoleList = userToRoleRepository.findByUserId(userId);

        //判断是否是施工队人员
        List<Integer> roleIdList = userToRoleList.stream().map(
                userToRole -> userToRole.getRoleId()).collect(Collectors.toList());

        return roleIdList.contains(RoleConstant.ROLE_POTEVOI_CONSTRUCTION_TEMM);
    }


//    public Page<WorkOrder> queryUnassingTaskByUserId(Integer userId, Pageable pageable) {
//        List<String> processInstanceIdList = activitiService.queryUnassingTaskByUserId(userId);
//
////        return workOrderCrudRepository.getAllByActProcInstIdIn(processInstanceIdList, pageable);
//        return null;
//    }

//    @Override
//    public void claim(Integer userId, String taskDefinitionKey,
//                      String processInstanceBusinessKey) throws Exception {
//        activitiService.claim(userId, taskDefinitionKey, processInstanceBusinessKey);
//    }

    @Override
    public void assignWorkOrders(Integer assignUserId, List<Long> workOrderIds) throws Exception {
        for (Long workOrderId : workOrderIds) {
            assignWorkOrder(assignUserId, workOrderId);
        }
    }


    private void assignWorkOrder(Integer assignUserId, Long workOrderId) throws Exception {
        //根据工单ID 找获取工单表及任务表
        WorkOrder workOrder = workOrderCrudRepository.findOne(workOrderId);
        List<SubTask> subTaskList = subTaskCrudRepository.findByWorkOrderId(workOrderId);

        //完成 activiti 分派工单任务,修改 施工单位任务候选人
        Map<String, String> organizationTeamMap = new HashMap<>();

        StringBuilder errorSB = new StringBuilder();
        for (SubTask subTask : subTaskList) {

            Organization organization = organizationRepository.findById(subTask.getOrganizationTeamId().intValue());

//            List<User> userList = userRepository.findByOrganizationCodeStartingWith(organization.getCode());
//            if (userList == null || userList.size() == 0) {
//                errorSB.append("【" + organization.getName() + "】没有查询到施工人员，请添加！\r\n");
//            }

//            List<Integer> userIdList = userList.stream().map(user -> user.getId()).collect(Collectors.toList());

            organizationTeamMap.put(subTask.getOrganizationTeamId() + "-" + subTask.getSubTaskId(),
                    organization.getCode());
        }

//        //如果有施工单位未添加人员 THROW EXCEPTION
//        if (errorSB.length() > 0) {
//            throw new Exception(errorSB.toString());
//        }

        Map<String, String> actRtuMap = activitiService
                .assignWorkOrder(String.valueOf(workOrder.getWorkOrderId()), assignUserId,
                        organizationTeamMap);

        //修改工单表及任务表属性,子任务关联 execution_id, 施工任务关连 act task id
        Date currentIime = new Date();
        User user = userRepository.findById(assignUserId);
        workOrder.setAssignWorkOrderUserId(assignUserId);
        workOrder.setAssignWorkOrderUserName(user.getDisplayName());
        workOrder.setAssignTime(currentIime);
        workOrder.setState(WorkOrderStatusEnum.EXECUTING.getCode());

        StringBuilder progressSB = new StringBuilder();
        SubTaskProcessInfo subTaskProcessInfo;
        SubTaskBusinessData subTaskBusinessData;
        for (SubTask subTask : subTaskList) {
            //设置子任务属性
            String executionId_actTaskId = actRtuMap
                    .get(subTask.getOrganizationTeamId() + "-" + subTask.getSubTaskId());
            subTask.setAssignTaskTime(currentIime);
            subTask.setCurrentOrganizationTeamId(subTask.getOrganizationTeamId());
            subTask.setActExecutionId(executionId_actTaskId.split(":")[0]);
            subTask.setSubTaskState(SubTaskStatusEnum.UNTREATED.getCode());

            //新建并保存业务数据表
            subTaskBusinessData = new SubTaskBusinessData();
            subTaskBusinessData.setSubTaskId(subTask.getSubTaskId());
            subTaskBusinessData.setWorkOrderId(subTask.getWorkOrderId());
            subTaskBusinessData.setDeviceId(subTask.getDeviceId());
            subTaskBusinessData.setDevicePosition(deviceRepository.findDeviceAddrsById(subTask.getDeviceId()));
            subTaskBusinessDataCrudRepository.save(subTaskBusinessData);

            //新建并保存流程信息表
            subTaskProcessInfo = new SubTaskProcessInfo();
            subTaskProcessInfo.setDeviceId(subTask.getDeviceId());
            subTaskProcessInfo.setWorkOrderId(subTask.getWorkOrderId());
            subTaskProcessInfo.setSubTaskId(subTask.getSubTaskId());
            subTaskProcessInfo.setProcessName(TaskProcessNameEnum.CONSTRUCTION.getMessage());
            subTaskProcessInfo.setActTaskId(executionId_actTaskId.split(":")[1]);
            subTaskProcessInfoCrudRepository.save(subTaskProcessInfo);

            Organization organization = organizationRepository
                    .findById(subTask.getOrganizationTeamId().intValue());

            progressSB.append(subTask.getSubTaskName()).append("(")
                    .append(SubTaskProcessStatusEnum.UNTREATED.getMessage()).append("),");

            subTaskCrudRepository.save(subTask);
        }

        if (progressSB.length() > 0) {
            workOrder.setProgress(progressSB.substring(0, progressSB.length() - 1));
        }
        workOrderCrudRepository.save(workOrder);
    }

    @Override
    public List<WorkOrder> queryNotAssignWorkOrderByUserId(Integer userId, int page, int size,
                                                           String order, String orderBy,
                                                           Long productLineId, String projectName,
                                                           String constructionTeamName, String deviceName,
                                                           Long deviceTypeId, Integer workOrderState) {

//        //判断是否是工程部人员
//        if (isEnginneringDept(userId) != true) {
//            return new ArrayList<>();
//        }

        List<UserToProductLine> list = userToProductLineService.findByUserId(userId);
        if (list != null && list.size() > 0) {//产品线角色
            productLineId = new Long((long) list.get(0).getProductLineId());
        }

        if (isConstructionTeam(userId)) {//施工队角色
            constructionTeamName = organizationRepository.findById(userRepository.findById(userId).getOrganizationId()).getName();
        }

        List<String> processInstanceIdList = activitiService.queryNotAssingTask();
        if (processInstanceIdList == null || processInstanceIdList.size() == 0) {
            return new ArrayList<>();
        }

        Sort.Direction der = order.equals(SystemConstant.DIRECTION_ASC) ? Sort.Direction.ASC : Sort.Direction.DESC;
        PageRequest request = new PageRequest(page - 1, size, new Sort(der, orderBy));

        return workOrderQueryRepository.queryWorkOrder(productLineId, projectName,
                constructionTeamName, deviceName, deviceTypeId,
                workOrderState, processInstanceIdList, request, null).getContent();
    }

    @Override
    public List<WorkOrder> queryWorkOrder(Integer userId, int page, int size, String order,
                                          String orderBy, Long productLineId, String projectName,
                                          String constructionTeamName, String deviceName,
                                          Long deviceTypeId, Integer workOrderState, String addr) {

        Sort.Direction der = order.equals(SystemConstant.DIRECTION_ASC) ? Sort.Direction.ASC : Sort.Direction.DESC;
        PageRequest request = new PageRequest(page - 1, size, new Sort(der, orderBy));

        List<UserToProductLine> list = userToProductLineService.findByUserId(userId);
        if (list != null && list.size() > 0) {//产品线角色
            productLineId = new Long((long) list.get(0).getProductLineId());
        }

        if (isConstructionTeam(userId)) {//施工队角色
            constructionTeamName = organizationRepository.findById(userRepository.findById(userId).getOrganizationId()).getName();
        }
        return workOrderQueryRepository.queryWorkOrder(productLineId, projectName,
                constructionTeamName, deviceName, deviceTypeId,
                workOrderState, null, request, addr).getContent();
    }


    @Override
    public TableJsonData findNotAssignWorkOrderByConditionJqg(Integer userId, TableDataQueryCondition cond) {
        TableJsonData data = findWorkOrderByConditionJqg(userId, cond, true);
        if (data == null) {
            data = new TableJsonData(cond, 0, new ArrayList<WorkOrder>());
        }
        return data;
    }

    @Override
    public TableJsonData findWorkOrderByConditionJqg(Integer userId, TableDataQueryCondition cond, Boolean isNotAssign) {
        PageRequest request = ServiceUtils.getPageRequestByTableDataQueryCondition(cond);

//        // 不是工程部人员并且不是 admin 用户
//        if((isEnginneringDept(userId) != true && !userId.equals(UserConstant.USER_AUTH_TYPE_SYSTE_ADMIN))
//                // 是 admin 用户并且是查询未分派工单
//                || (userId.equals(UserConstant.USER_AUTH_TYPE_SYSTE_ADMIN) && isNotAssign == true) ){
//            return null;
//        }

        List<String> processInstanceIdList = null;
        if (isNotAssign != null && isNotAssign == true) {
            processInstanceIdList = activitiService.queryNotAssingTask();
            if (processInstanceIdList == null || processInstanceIdList.size() == 0) {
                return new TableJsonData(cond, 0, new ArrayList<WorkOrder>());
            }
        }

        Map queryCondMap = cond.getQueryCond();
        String productLineIdStr = (String) queryCondMap.get("productLineId");
        Long productLineId = null;
        if (StringUtil.isNotEmpty(productLineIdStr)) {
            productLineId = Long.valueOf(productLineIdStr);
        }
        List<UserToProductLine> list = userToProductLineService.findByUserId(userId);
        if (list != null && list.size() > 0) {//产品线角色
            productLineId = new Long((long) list.get(0).getProductLineId());
        }

        String projectName = (String) queryCondMap.get("projectName");
        String constructionTeamName = (String) queryCondMap.get("constructionTeamName");

        if (isConstructionTeam(userId)) {//施工队角色
            constructionTeamName = organizationRepository.findById(userRepository.findById(userId).getOrganizationId()).getName();
        }

        String deviceName = (String) queryCondMap.get("deviceName");
        String deviceTypeIdStr = (String) queryCondMap.get("deviceTypeId");
        Long deviceTypeId = null;
        if (StringUtil.isNotEmpty(deviceTypeIdStr)) {
            deviceTypeId = Long.valueOf(deviceTypeIdStr);
        }
        String workOrderStateStr = (String) queryCondMap.get("workOrderState");
        Integer workOrderState = null;
        if (StringUtil.isNotEmpty(workOrderStateStr)) {
            workOrderState = Integer.valueOf(workOrderStateStr);
        }

        Page<WorkOrder> workOrderPage = workOrderQueryRepository.queryWorkOrder(productLineId, projectName,
                constructionTeamName, deviceName, deviceTypeId,
                workOrderState, processInstanceIdList, request, null);

        return new TableJsonData(cond, workOrderPage.getTotalElements(), workOrderPage.getContent());
    }

    @Override
    public List<WorkOrder> queryWorkOrder(Integer userId, Long productLineId,
                                          String projectName, String constructionTeamName,
                                          String deviceName, Long deviceTypeId, Integer workOrderState) {

        List<UserToProductLine> list = userToProductLineService.findByUserId(userId);
        if (list != null && list.size() > 0) {//产品线角色
            productLineId = new Long((long) list.get(0).getProductLineId());
        }


        if (isConstructionTeam(userId)) {//施工队角色
            constructionTeamName = organizationRepository.findById(userRepository.findById(userId).getOrganizationId()).getName();
        }

        //查询工单列表
        List<WorkOrder> workOrderList = workOrderQueryRepository.queryWorkOrderByCondition(productLineId,
                projectName, constructionTeamName, deviceName, deviceTypeId, workOrderState, null);

        List<WorkOrderType> workOrderTypeList = workOrderTypeRepository.findAll();
        Map<Long, String> workOrderTypeMap = new HashMap<>();
        for (WorkOrderType workOrderType : workOrderTypeList) {
            workOrderTypeMap.put(workOrderType.getId(), workOrderType.getName());
        }
        //查询子任务列表
        for (WorkOrder workOrder : workOrderList) {
            List<SubTask> subTaskList = subTaskCrudRepository.findByWorkOrderId(workOrder.getWorkOrderId());
            for (SubTask subTask : subTaskList) {
                subTask.setWorkOrderTypeName(workOrderTypeMap.get(subTask.getWorkOrderTypeId()));
            }

            workOrder.setSubTaskList(subTaskList);
        }


        return workOrderList;
    }


    @Override
    public WorkOrder getWorkOrderById(Long workOrderId) {

        WorkOrder workOrder = workOrderQueryRepository.queryWorkOrderById(workOrderId);
        List<SubTask> subTaskList = subTaskCrudRepository.findByWorkOrderId(workOrderId);

//        List<SubTaskProcessInfo> subTaskProcessInfoList = new ArrayList<>();
        for (SubTask subTask : subTaskList) {
            //获取子任务
            SubTask subTaskTmp = subTaskService.querySubTaskById(subTask.getSubTaskId());

            ProcessRule processRule = processRuleService.findByProcessRuleByDeviceTypeOrderTypeProject(
                    subTaskTmp.getDeviceTypeId(), subTaskTmp.getWorkOrderTypeId(), subTaskTmp.getProjectId());
            subTaskTmp.setProcessRule(processRule);

            //添加子任务
            workOrder.getSubTaskList().add(subTaskTmp);
            //添加子任务流程
//            subTaskProcessInfoList.addAll(subTaskTmp.getSubTaskProcessInfoList());
        }

//        workOrder.getAllSubTaskProcessInfoList().addAll(subTaskProcessInfoList);
        return workOrder;
    }

    @Override
    public List<WorkOrder> findAll() {
        return workOrderCrudRepository.findAll();
    }
}
